package com.xs.micro.tool.config.prop;

import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.xs.micro.tool.config.prop.sub.BankInfoConfig;
import com.xs.micro.tool.config.prop.sub.IdCardBeginNoConfig;
import com.xs.micro.tool.domain.pojo.contants.RandomPeopleInfoDataContants;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

/**
 * 应用配置类，应用级别的所有配置统一入口<br>
 * 不建议将配置进行分散管理，原则上一个项目中仅有一个@ConfigurationProperties注解文件。<br>
 * 并且建议应用级别配置均以app.conf开头，用以和框架配置做命名空间区分
 *
 * @author guochaohui
 */
@Component
@ConfigurationProperties(prefix = "app.conf")
@Slf4j
public class AppPropertiesConfig {

    private List<BankInfoConfig> bankInfoList;
    private String mobileInfoBeginNo;
    private String lastName;
    private String femaleName;
    private String maleName;

    private String idCardBeginNoContext;
    private String idCardBeginNoFile;

    private List<IdCardBeginNoConfig> idCardBeginNoProvinceList;
    private Map<String, List<IdCardBeginNoConfig>> idCardBeginNoCityMap;
    private Map<String, List<IdCardBeginNoConfig>> idCardBeginNoCountyMap;
    private Map<String, IdCardBeginNoConfig> idCardBeginNoAllMap;

    private List<String> mobileInfoBeginNoList;
    private List<String> lastNameList;
    private List<String> femaleNameList;
    private List<String> maleNameList;

    public List<BankInfoConfig> getBankInfoList() {
        return bankInfoList;
    }

    public void setBankInfoList(List<BankInfoConfig> bankInfoList) {
        this.bankInfoList = bankInfoList;
    }

    public String getMobileInfoBeginNo() {
        return mobileInfoBeginNo;
    }

    public void setMobileInfoBeginNo(String mobileInfoBeginNo) {
        this.mobileInfoBeginNo = mobileInfoBeginNo;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getFemaleName() {
        return femaleName;
    }

    public void setFemaleName(String femaleName) {
        this.femaleName = femaleName;
    }

    public String getMaleName() {
        return maleName;
    }

    public void setMaleName(String maleName) {
        this.maleName = maleName;
    }

    public String getIdCardBeginNoContext() {
        return idCardBeginNoContext;
    }

    public void setIdCardBeginNoContext(String idCardBeginNoContext) {
        this.idCardBeginNoContext = idCardBeginNoContext;
    }

    public String getIdCardBeginNoFile() {
        return idCardBeginNoFile;
    }


    public void setIdCardBeginNoFile(String idCardBeginNoFile) {
        this.idCardBeginNoFile = idCardBeginNoFile;
    }

    public List<IdCardBeginNoConfig> getIdCardBeginNoProvinceList() {
        return idCardBeginNoProvinceList;
    }

    public Map<String, List<IdCardBeginNoConfig>> getIdCardBeginNoCityMap() {
        return idCardBeginNoCityMap;
    }

    public Map<String, List<IdCardBeginNoConfig>> getIdCardBeginNoCountyMap() {
        return idCardBeginNoCountyMap;
    }

    public Map<String, IdCardBeginNoConfig> getIdCardBeginNoAllMap() {
        return idCardBeginNoAllMap;
    }

    public List<String> getMobileInfoBeginNoList() {
        return mobileInfoBeginNoList;
    }

    public List<String> getLastNameList() {
        return lastNameList;
    }

    public List<String> getFemaleNameList() {
        return femaleNameList;
    }

    public List<String> getMaleNameList() {
        return maleNameList;
    }

    public void initialConfig() {
        try {
            if (CollectionUtils.isEmpty(mobileInfoBeginNoList) && StringUtils.isNotBlank(mobileInfoBeginNo)) {
                mobileInfoBeginNoList = Splitter.on(",").omitEmptyStrings().splitToList(mobileInfoBeginNo);
            }
            if (CollectionUtils.isEmpty(lastNameList) && StringUtils.isNotBlank(lastName)) {
                lastNameList = Splitter.on(",").omitEmptyStrings().splitToList(lastName);
            }
            if (CollectionUtils.isEmpty(femaleNameList) && StringUtils.isNotBlank(femaleName)) {
                femaleNameList = Splitter.on(",").omitEmptyStrings().splitToList(femaleName);
            }
            if (CollectionUtils.isEmpty(maleNameList) && StringUtils.isNotBlank(maleName)) {
                maleNameList = Splitter.on(",").omitEmptyStrings().splitToList(maleName);
            }

            List dataList = Lists.newArrayList();

            File file = new File(idCardBeginNoFile);
            if (file.exists() && file.isFile()) {
                log.info("readIdCardBeginNoFile from file. {}", idCardBeginNoFile);

                try (FileInputStream inputStream = new FileInputStream(file)) {
                    dataList = IOUtils.readLines(inputStream, StandardCharsets.UTF_8.name());
                }
            } else {
                log.info("readIdCardBeginNoFile from yml. {}", idCardBeginNoFile);
                String context = StringUtils.defaultIfBlank(idCardBeginNoContext, StringUtils.EMPTY);
                dataList = Splitter.on(",").splitToList(context);
            }

            if (CollectionUtils.isEmpty(dataList)) {
                log.error("readIdCardBeginNoFile is empty. skip. file={}", idCardBeginNoFile);
                dataList = Lists.newArrayList();
            }

            idCardBeginNoProvinceList = Lists.newArrayList();
            idCardBeginNoCityMap = Maps.newHashMap();
            idCardBeginNoCountyMap = Maps.newHashMap();
            idCardBeginNoAllMap = Maps.newHashMap();

            for (Object obj : dataList) {
                if (obj == null) {
                    continue;
                }
                String data = String.valueOf(obj);
                if (StringUtils.isBlank(data)) {
                    continue;
                }
                String[] dataArr = data.split(RandomPeopleInfoDataContants.SPLIT_DATA_INFO_STR);
                String code = dataArr[0];
                String name = dataArr[dataArr.length - 1];
                IdCardBeginNoConfig idCardBeginNoConfig = new IdCardBeginNoConfig(code, name);
                int count = StringUtils.countMatches(data, RandomPeopleInfoDataContants.SPLIT_DATA_INFO_STR);
                switch (count) {
                    case 1:
                        idCardBeginNoProvinceList.add(idCardBeginNoConfig);
                        break;
                    case 2:
                        String provincePrefix = StringUtils.left(code, RandomPeopleInfoDataContants.PROVINCE_CODE_PREFIX_LENGTH);
                        List<IdCardBeginNoConfig> cityList = (List<IdCardBeginNoConfig>) MapUtils.getObject(idCardBeginNoCityMap, provincePrefix, Lists.newArrayList());
                        cityList.add(idCardBeginNoConfig);
                        idCardBeginNoCityMap.put(provincePrefix, cityList);
                        break;
                    case 4:
                        String cityPrefix = StringUtils.left(code, RandomPeopleInfoDataContants.CITY_CODE_PREFIX_LENGTH);
                        List<IdCardBeginNoConfig> countyList = (List<IdCardBeginNoConfig>) MapUtils.getObject(idCardBeginNoCountyMap, cityPrefix, Lists.newArrayList());
                        countyList.add(idCardBeginNoConfig);
                        idCardBeginNoCountyMap.put(cityPrefix, countyList);
                        break;
                    default:
                        break;
                }
                idCardBeginNoAllMap.put(code, idCardBeginNoConfig);
            }
            checkIdCardBeginNo();
        } catch (Exception e) {
            log.error("readIdCardBeginNoFile error. skip.", e);
        }
    }

    private void checkIdCardBeginNo() {
        List<String> errorList = Lists.newArrayList();
        for (IdCardBeginNoConfig province : idCardBeginNoProvinceList) {
            String provincePrefix = StringUtils.left(province.getCode(), RandomPeopleInfoDataContants.PROVINCE_CODE_PREFIX_LENGTH);
            List<IdCardBeginNoConfig> cityList = idCardBeginNoCityMap.get(provincePrefix);
            if (CollectionUtils.isEmpty(cityList)) {
                errorList.add("省 " + province.getName() + " 下级市 空");
            }
        }
        for (Map.Entry<String, List<IdCardBeginNoConfig>> entry : idCardBeginNoCityMap.entrySet()) {
            List<IdCardBeginNoConfig> cityList = entry.getValue();
            for (IdCardBeginNoConfig city : cityList) {
                String cityPrefix = StringUtils.left(city.getCode(), RandomPeopleInfoDataContants.CITY_CODE_PREFIX_LENGTH);
                List<IdCardBeginNoConfig> countyList = idCardBeginNoCountyMap.get(cityPrefix);
                if (CollectionUtils.isEmpty(countyList)) {
                    errorList.add("市 " + city.getName() + " 下级区/县 空");
                }
            }
        }
        Assert.isTrue(CollectionUtils.isEmpty(errorList), Joiner.on(",").join(errorList));
    }

}

